package com.xms.security.api.controller;

import com.xms.core.enums.AccessRightValue;
import com.xms.core.exception.XmsException;
import com.xms.core.module.ModuleCollection;
import com.xms.schema.service.entity.IEntityFinderService;
import com.xms.sdk.core.DynamicData;
import com.xms.sdk.service.IDataFinder;
import com.xms.security.core.EntityPermissionDefaults;
import com.xms.security.entity.EntityPermission;
import com.xms.security.entity.RoleObjectAccess;
import com.xms.security.service.dataauth.IEntityPermissionFinderService;
import com.xms.security.service.dataauth.IRoleObjectAccessService;
import com.xms.utils.CollectionUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import com.xms.web.framework.controller.ApiBaseController;
import com.xms.web.framework.model.JsonResultObject;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * RoleEntityPermissionController
 * </p>
 *
 * @author migo
 * @since 2021/9/25
 */
@RestController
@RequestMapping("/{org}/api/security/roleentitypermission")
public class RoleEntityPermissionController extends ApiBaseController {
    private IEntityPermissionFinderService _entityPermissionFinderService;
    private IEntityFinderService _entityFinderService;
    private IRoleObjectAccessService _roleObjectAccessService;
    private IDataFinder _dataFinder;

    @Autowired
    public RoleEntityPermissionController(IEntityPermissionFinderService entityPermissionFinderService,
                                          IEntityFinderService entityFinderService,
                                          IRoleObjectAccessService roleObjectAccessService,
                                          IDataFinder dataFinder)
    {
        _entityPermissionFinderService = entityPermissionFinderService;
        _entityFinderService = entityFinderService;
        _roleObjectAccessService = roleObjectAccessService;
        _dataFinder = dataFinder;
    }

    @ApiOperation("角色实体权限配置信息")
    @GetMapping("")
    public JsonResultObject get(@RequestParam(value = "roleid", required = true) UUID roleid) throws XmsException, SQLException {
        //查询角色实体权限
        List<RoleObjectAccess> roleObjectAccesses = _roleObjectAccessService.getRolePermissions(roleid, ModuleCollection.getIdentity(EntityPermissionDefaults.MODULE_NAME));
        //查询实体分组
        List<com.xms.core.data.Entity> entityGroups = _dataFinder.retrieveAll("entitygroup");
        com.xms.core.data.Entity emptyGroup = new com.xms.core.data.Entity("entitygroup");
        emptyGroup.setIdValue(UUIDUtil.Empty).setValue("name", "未分组");
        entityGroups.add(emptyGroup);
        List<UUID> groupIds = entityGroups.stream().map(g->g.getIdValue()).collect(Collectors.toList());
        //查询实体信息
        List<com.xms.schema.entity.Entity> entities = _entityFinderService.all();
        //分组为空或不存在的都归到未分组
        entities.forEach(x->{
            if(StringUtil.isEmpty(x.getEntitygroups())){
                x.setEntitygroups(UUIDUtil.Empty.toString());
            }
            boolean exists = groupIds.stream().anyMatch(g->x.getEntitygroups().contains(g.toString()));
            if(!exists) x.setEntitygroups(UUIDUtil.Empty.toString());
        });
        //查询实体权限项
        List<EntityPermission> entityPermissions = _entityPermissionFinderService.all();
        List<DynamicData> result = new ArrayList<>();
        //分组
        for (com.xms.core.data.Entity group : entityGroups){
            DynamicData groupMap = new DynamicData();
            groupMap.put("id", group.getIdValue());
            groupMap.put("label", group.getStringValue("name"));
            List<com.xms.schema.entity.Entity> groupEntities = entities.stream().filter(x -> x.getAuthorizationenabled() && x.getEntitygroups().contains(group.getIdValue().toString())).collect(Collectors.toList());
            if(CollectionUtil.isEmpty(groupEntities)) continue;
            List<DynamicData> entityMapList = new ArrayList<>();
            //实体
            for (com.xms.schema.entity.Entity ent : groupEntities){
                DynamicData entityMap = new DynamicData();
                entityMap.put("id", ent.getEntityid());
                entityMap.put("label", ent.getLocalizedname());
                entityMap.put("name", ent.getName());
                entityMap.put("mask", ent.getEntitymask());
                List<EntityPermission> entPermissions = entityPermissions.stream().filter(x -> x.getAccessright() != AccessRightValue.Export.value() && x.getAccessright() != AccessRightValue.Import.value() && x.getEntityid().equals(ent.getEntityid())).sorted(Comparator.comparing(EntityPermission::getAccessright)).collect(Collectors.toList());
                List<DynamicData> entityPmsList = new ArrayList<>();
                //实体权限项
                for (EntityPermission ep : entPermissions){
                    DynamicData entityPmsMap = new DynamicData();
                    entityPmsMap.put("id", ep.getEntitypermissionid());
                    entityPmsMap.put("label", ep.getName());
                    entityPmsMap.put("mask", ep.getAccessright());
                    //是否已授权给角色
                    RoleObjectAccess assigned = roleObjectAccesses.stream().filter(x->x.getObjectid().equals(ep.getEntitypermissionid())).findFirst().orElse(null);
                    entityPmsMap.put("assignedmask", assigned != null ? assigned.getAccessrightsmask() : 0);
                    entityPmsList.add(entityPmsMap);
                }
                entityMap.put("children", entityPmsList);
                entityMapList.add(entityMap);
            }
            groupMap.put("children", entityMapList);
            result.add(groupMap);
        }
        return JOk(result);
    }
}
